import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // ChangeNotifierProvider 创建状态并将其提供给整个应用。这样一来，应用中的任何 widget 都可以获取状态。
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Namer App',
        theme: ThemeData(
          useMaterial3: true,
          // Color.fromARGB(255, 16, 247, 12)  Colors.deepOrange 或 Colors.red
          // 使用十六进制数，也可以使用 Color(0xFF00FF00)
          // 完全不透明的纯色 fromRGBO
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
        ),
        home: MyHomePage(),
      ),
    );
  }
}

// 定义应用的状态（管理应用状态）
// 定义应用运行所需的数据
// 状态类扩展 ChangeNotifier，这意味着它可以向其他人通知自己的更改。例如，如果当前单词对发生变化，应用中的一些 widget 需要知晓此变化。
class MyAppState extends ChangeNotifier {
  var current = WordPair.random();
  void getNext() {
    current = WordPair.random();
    // 通知所有监听器，状态已更改。向任何通过 watch 方法跟踪 MyAppState 的对象发出通知。
    notifyListeners();
  }

  // 增加“收藏”
  var favorites = <WordPair>[];
  void toggleFavorite() {
    if (favorites.contains(current)) {
      favorites.remove(current);
    } else {
      favorites.add(current);
    }
    // 通知所有监听器，状态已更改。向任何通过 watch 方法跟踪 MyAppState 的对象发出通知。
    notifyListeners();
  }
}

class MyHomePage extends StatelessWidget {
  @override
  // 每个 widget 均定义了一个 build() 方法，每当 widget 的环境发生变化时，系统都会自动调用该方法，以便 widget 始终保持最新状态。
  Widget build(BuildContext context) {
    // 使用 watch 方法跟踪对应用当前状态的更改。
    var appState = context.watch<MyAppState>();
    var wordPair = appState.current;

    // 图标
    IconData icon;
    if (appState.favorites.contains(wordPair)) {
      icon = Icons.favorite;
    } else {
      icon = Icons.favorite_border;
    }

    // 每个 build 方法都必须返回一个 widget 或（更常见的）嵌套 widget 树。在本例中，顶层 widget 是 Scaffold。
    return Scaffold(
      // Column 是 Flutter 中最基础的布局 widget 之一。它接受任意数量的子项并将这些子项从上到下放在一列中。默认情况下，该列会以可视化形式将其子项置于顶部。
      body: Center(
        // 环绕一个居中，Wrap with Center
        child: Column(
          // 居中
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Text('A random AWESOME idea:'),
            // 第二个 Text widget 接受 appState，并访问该类的唯一成员 current（这是一个 WordPair）。WordPair 提供了一些有用的 getter，例如 asPascalCase 或 asSnakeCase。此处，我们使用了 asLowerCase。
            // Text(appState.current.asLowerCase), 修改appState的current
            // 提取widget Extract Widget
            NewWidget(wordPair: wordPair),
            // 增加间隙
            SizedBox(height: 10),
            // ↓ Add this.
            Row(
              // 居中
              // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              // 告知 Row 不要占用所有可用的水平空间
              mainAxisSize: MainAxisSize.min,
              children: [
                // 带图标的按钮（标签 label）
                ElevatedButton.icon(
                  onPressed: () {
                    appState.toggleFavorite();
                  },
                  icon : Icon(icon),
                  label: Text('Like'),
                ),
                SizedBox(width: 10),
                // 行级旁边加一个：Wrap with Row
                ElevatedButton(
                  onPressed: () {
                    // print('button pressed!');
                    appState.getNext();
                  },
                  child: Text('Next'),
                ),
              ],
            ),
          ], // 请注意，Flutter 代码大量使用了尾随逗号。此处并不需要这种特殊的逗号，但建议在 Flutter 中使用它们，因为它们可以减少代码中的错误。
        ),
      ),
    );
  }
}

class NewWidget extends StatelessWidget {
  const NewWidget({
    super.key,
    required this.wordPair,
  });

  final WordPair wordPair;

  @override
  Widget build(BuildContext context) {
    // 获取主题
    final theme = Theme.of(context);
    // 获取文本样式
    // 创建新的文本样式，并使用 copyWith 方法来修改它
    // copyWith 方法允许您创建一个新样式，而不会修改原始样式。
    // 字体主题。此类包括以下成员：bodyMedium（针对中等大小的标准文本）、caption（针对图片的说明）或 headlineLarge（针对大标题）
    // 调用 displayMedium 上的 copyWith() 会返回文本样式的副本，以及您定义的更改。在本例中，您只是更改文本的颜色。
    final style = theme.textTheme.headlineMedium!.copyWith(
      color: theme.colorScheme.onPrimary,
    );

    return Card(
      elevation: 9,
      color: theme.colorScheme.primary,
      // 环绕padding widget，用 widget 环绕： Wrap with widget
      child: Padding(
        // 上下边距
        padding: const EdgeInsets.all(20.0),
        // child: Text(wordPair.asUpperCase),
        // 环绕text widget，用padding环绕： Wrap with Padding
        child: Text(
          wordPair.asLowerCase, 
          style: style,
          semanticsLabel: "${wordPair.first} ${wordPair.second}",
        ),
      ),
    );
  }
}
